#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import ftplib
from ftplib import FTP
from matplotlib.font_manager import FontProperties
import numpy as np
import datetime
import csv
import matplotlib.pyplot as plt
from tqdm import tqdm

# FTP登录信息
ftp_host = '112.95.225.155'
ftp_user = 'log'
ftp_password = '123456'

# start_timestamp = '2025-05-19_10.00.00'
# end_timestamp = '2025-05-26_00.00.00'
start_timestamp = '2025-05-16_00.00.00'
end_timestamp = '2025-05-22_00.00.00'

# 保存目录
save_directory = '/mnt/HDD/home/ubuntu/BAG/版本发布AB轮/三月版本/自行跟踪'

error_codes = []
search_sn=[]
# Get current date and time
current_datetime = datetime.datetime.now()
# Format the date and time as string
date_time_string = current_datetime.strftime("%Y-%m-%d-%H-%M-%S")

# 读取CSV文件中的错误码
with open('error_codes.csv', 'r', encoding='utf-8') as file:
    # 创建CSV读取器
    reader = csv.reader(file)
    # 读取CSV文件的每一行
    for row in reader:
        if len(row) > 0:
            error_code = row[0]  # 假设错误码列是第一列
            error_codes.append(error_code)
        # else:
        #     print("row is empty or too short")
print("error_codes:", error_codes)

# 连接FTP服务器
ftp = FTP(ftp_host, timeout=30.0)
ftp.login(user=ftp_user, passwd=ftp_password)

# 搜索文件夹并下载文件
# 打开CSV文件
with open('robot_sn.csv', 'r', encoding='utf-8') as file:
    # 创建CSV读取器
    reader = csv.reader(file)
    # 读取CSV文件的每一行
    for row in reader:
        if len(row) > 0:
            print("sn:", row)
            sn = row[0]  # 假设SN列是第一列
            search_sn.append(sn)
        # else:
        #     print("row is empty or too short")
# print("search_sn:", search_sn)

# 获取FTP根目录下的所有文件夹
ftp.cwd('/')
folders = ftp.nlst()
print("Size of folders:", len(folders))

# 存储结果的列表
file_list = []
sn_file_count = {}
error_code_count = {}
timestamp_count = {}

# 遍历文件夹
for folder in tqdm(folders):
    # print("Folder:", folder)
    # 检查文件夹名称是否包含  **指定的sn**  且以"hotel."和"ktv."开头
    # if (folder.startswith("hotel.") or folder.startswith("ktv.")) and any(sn in folder for sn in search_sn):
    # 检查文件夹名以"hotel."、"ktv."开头且不包含 temporary 的文件夹
    # if (folder.startswith("hotel.") or folder.startswith("ktv.")) and "temporary" not in folder:  #and any(sn in folder for sn in search_sn)
    # 检查所有文件夹是以"hotel."、"ktv."开头的文件夹
    if (folder.startswith("hotel.") or folder.startswith("ktv.")):
        print("Hit Folder:", folder)
        # 进入文件夹
        try:
            ftp.cwd(folder)
        except ftplib.error_perm as e:
            print(f'无法进入目录"{folder}"：{e}')
            continue
        files = ftp.nlst()
        
        # 遍历文件
        for file in files:
            if file.endswith('.tar'):
                # 提取文件名中的时间戳和错误码
                file_parts = file.split('_')
                # print("file:", file)
                if len(file_parts) >= 5:
                    timestamp = file_parts[0] + '_' + file_parts[1]
                    error_code = file_parts[4]
                    
                    # 检查时间戳是否在给定区间内且错误码在给定列表中
                    if start_timestamp <= timestamp <= end_timestamp and (not error_codes or error_code in error_codes):
                        # 创建以sn为名的文件夹
                        sn = folder.split('_')[-1]
                        # sn_folder = os.path.join(save_directory, sn)
                        sn_folder = os.path.join(save_directory+ "bag-" +date_time_string+ "/", folder)
                        # if not os.path.exists(sn_folder):
                        os.makedirs(sn_folder, exist_ok=True)

                        # 下载文件到本地文件夹
                        local_file = os.path.join(sn_folder, file)
                        if os.path.exists(local_file):
                            print(f'文件"{local_file}"已存在')
                            continue

                        try:
                            with open(local_file, 'wb') as f:
                                ftp.retrbinary('RETR ' + file, f.write, blocksize=8192)
                        except ftplib.error_perm as e:
                            print(f'无法下载文件"{file}"：{e}')
                            continue
                        # 添加文件信息到结果列表
                        file_list.append([sn, file, timestamp, error_code])
                        
                        # 统计每个sn码对应的文件数量、错误码数量和时间戳数量
                        sn_file_count[sn] = sn_file_count.get(sn, 0) + 1
                        error_code_count[sn] = error_code_count.get(sn, 0) + 1
                        timestamp_count[sn] = timestamp_count.get(sn, 0) + 1
                else:
                    print(f'文件名"{file}"不符合格式要求')
            
        # 返回上级目录
        ftp.cwd('..')

# 关闭FTP连接
ftp.quit()

# 统计每个sn的各个错误码出现的次数以及对应的文件
sn_error_count = {}
sn_error_files = {}
error_code_count = {}
error_code_files = {}

for sn, file, timestamp, error_code in file_list:
    if sn not in sn_error_count:
        sn_error_count[sn] = {}
        sn_error_files[sn] = {}
    
    if error_code not in sn_error_count[sn]:
        sn_error_count[sn][error_code] = 0
        sn_error_files[sn][error_code] = []
    
    sn_error_count[sn][error_code] += 1
    sn_error_files[sn][error_code].append(file)

    if error_code not in error_code_count:
        error_code_count[error_code] = 0
        error_code_files[error_code] = []
    
    error_code_count[error_code] += 1
    error_code_files[error_code].append(file)

# Write report to a text file
report_folder = os.path.join(save_directory, "report-" +date_time_string + "/")
if not os.path.exists(report_folder):
    os.makedirs(report_folder)

file_name = os.path.join(report_folder, date_time_string + ".txt")
error_codes = set()
# 统计搜索到的SN数量
num_sns_searched = len(search_sn)
# 统计包含目标文件的SN数量
num_sns_with_files = len([sn for sn in sn_file_count if sn_file_count[sn] > 0])

# Sort SNs by the number of files in descending order
sorted_sns = sorted(sn_file_count, key=lambda sn: sn_file_count[sn], reverse=True)
sorted_error_codes = sorted(error_code_count, key=lambda error_code: error_code_count[error_code], reverse=True)

report = ""
report += f"搜索到的SN数量：{num_sns_searched}\n"
report += f"包含目标文件的SN数量：{num_sns_with_files}\n"
report += f"搜索到的文件数量：{len(file_list)}\n"

report += "-----------------------------------\n"
# Sort error codes by the number of files in descending order

report += "按拥有文件数由多到少排列的SN列表:\n"
for sn in sorted_sns:
    report += f"{sn} ({sn_file_count.get(sn, 0)} files)\n"
report += "-----------------------------------\n"

report += "按拥有文件数由多到少排列的错误码列表:\n"
for error_code in sorted_error_codes:
    report += f"{error_code} ({error_code_count.get(error_code, 0)} files)\n"
report += "-----------------------------------\n"
report += "\n"
report += "\n"
report += "详细信息:\n"
report += "\n"

for sn in sorted_sns:
    error_count = sn_error_count[sn]
    report += f"SN: {sn} ({sn_file_count.get(sn, 0)} files)\n"
    for error_code, count in error_count.items():
        report += f"错误码: {error_code}, 出现次数: {count}\n"
        report += "对应的文件:\n"
        for file in sn_error_files[sn][error_code]:
            report += file + "\n"
        report += "\n"
    error_codes.update(error_count.keys())

print(report)  # Print the report
print("统计结果保存在:", file_name)

if file_list == []:
    print("没有找到符合条件的文件")
    exit(0)
# Write the report to a text file
with open(file_name, "w") as f:
    f.write(report)
    f.close()

# Prepare data for plotting
sn_list = list(sn_error_count.keys())
error_code_list = list(error_codes)
counts = np.zeros((len(sn_list), len(error_code_list)))

for i, sn in enumerate(sn_list):
    error_count = sn_error_count[sn]
    for j, error_code in enumerate(error_code_list):
        counts[i, j] = error_count.get(error_code, 0)

# Set color map
cmap = plt.get_cmap('tab10')

# Plot the bar chart
fig, ax = plt.subplots()
width = 0.8 / len(error_code_list)
for i in range(len(error_code_list)):
    ax.bar(np.arange(len(sn_list)) + i * width, counts[:, i], width=width, label=error_code_list[i], color=cmap(i))

ax.set_xlabel('SN')
ax.set_ylabel('Error Code Count')
ax.set_title('Error Code Count by SN')
ax.set_xticks(np.arange(len(sn_list)))
ax.set_xticklabels([f"{sn} ({sn_file_count[sn]})" for sn in sn_list], rotation=20, ha='center')  # 调整标签的旋转角度和对齐方式
ax.legend()

# Add error code labels to the bars
for i in range(len(error_code_list)):
    for j in range(len(sn_list)):
        count = counts[j, i]
        if count > 0:
            error_code = error_code_list[i]
            ax.text(j + i * width, count, str(int(count)), ha='center', va='bottom')
            if error_code=="active":
                ax.text(j + i * width, count-0.3, error_code, ha='center', va='top', rotation=90, fontsize=8)
            else:
                ax.text(j + i * width, count-0.3, error_code, ha='center', va='top', rotation=0, fontsize=8)

figure=plt.gcf()
figure.set_size_inches(20, 10)
plt.subplots_adjust(bottom=0.3)
# Save the plot as an image
plt.tight_layout()  # 调整图像布局，确保标签完全显示
plt.savefig(save_directory + "/report-" + date_time_string+ "/" + date_time_string + ".png")
plt.show()
